
#include "scps.h"
#include "scpstp.h"
#include "scpserrno.h"
#include "tp_debug.h"
#include <stdio.h>
#include <math.h>
#include "route.h"
#include "rt_alloc.h"
#include "scps_ip.h"
#include "scps_np.h"
#include "rs_config.h"
#include "new_compress.h"
#include "tp_socket.h"

int scps_np_get_template (scps_np_rqts * rqts, scps_np_template * templ);


extern GW_ifs gw_ifs;
extern route *def_route;
extern route *other_route;

extern tp_Socket *tp_allsocs;  /* Pointer to first TP socket */
extern uint32_t tp_now;
int delayed_sent;
extern short tp_id;
extern int cluster_check;

struct llbuf *in_data;      /* packet buffer */


int tp_CompressedHandler (scps_np_rqts * rqts, int len, tp_Header * tp)
{
  tp_Socket *s;
  tp_PseudoHeader ph;
  byte *cp;
  uint16_t cks;
  int chl;

  cp = (byte *) tp;

  /* demux to active sockets */
  for (s = tp_allsocs; s; s = s->next) {
      if (((s->nl_protocol_id == NL_PROTOCOL_IPV4) &&
          ((htonl (rqts->ipv4_src_addr) == s->his_ipv4_addr))) ||

          ((s->nl_protocol_id == NL_PROTOCOL_NP) &&
          ((htonl (rqts->ipv4_src_addr) == s->his_ipv4_addr))) ||

          ((s->nl_protocol_id == NL_PROTOCOL_IPV6) &&
          (memcmp (&(rqts->ipv6_src_addr), &(s->his_ipv6_addr), sizeof (struct in6_addr))))) {

                break;
      }
    }
  if (s == NULL)
    {
      return (0);
    }

  if (rqts->nl_protocol == NL_PROTOCOL_IPV4) {
        ph.nl_head.ipv4.src = htonl (rqts->ipv4_src_addr);
        ph.nl_head.ipv4.dst = htonl (rqts->ipv4_dst_addr);
        ph.nl_head.ipv4.mbz = 0;
                /* pseudo header checksum still assumes TP */
        ph.nl_head.ipv4.protocol = IPPROTO_TCP;
        ph.nl_head.ipv4.length = htons (len);
        ph.nl_head.ipv4.checksum = checksum ((uint16_t *) tp, ntohs (ph.nl_head.ipv4.length));
         cks = checksum ((uint16_t *) & ph.nl_head.ipv4, 14);
  if (cks != 0xffff)
    {
        /* Cksum failed with protocol IPPROTO_TCP - Let's try SCPSCTP */
         ph.nl_head.ipv4.protocol = SCPSCTP;
         cks = checksum ((uint16_t *) & ph, 14);
         if (cks != 0xffff) {
             LOG ("Checkum failure \n");
             return (0);                /* Disregard on checksum failure */
         }
    }
  }
  if (rqts->nl_protocol == NL_PROTOCOL_IPV6) {
        ntoh16 (ph.nl_head.ipv6.src.s6_addr, rqts->ipv6_src_addr.s6_addr);
        ntoh16 (ph.nl_head.ipv6.dst.s6_addr, rqts->ipv6_dst_addr.s6_addr);
        ph.nl_head.ipv6.mbz1 = 0;
        ph.nl_head.ipv6.mbz2 = 0;
        ph.nl_head.ipv6.mbz3 = 0;
                /* pseudo header checksum still assumes TP */
        ph.nl_head.ipv6.protocol = IPPROTO_TCP;
        ph.nl_head.ipv6.length = htonl (((long) len));
        ph.nl_head.ipv6.checksum = checksum ((uint16_t *) tp, len);
        cks = checksum ((uint16_t *) & ph.nl_head.ipv6, 42);
  if (cks != 0xffff)
    {
        /* Cksum failed with protocol IPPROTO_TCP - Let's try SCPSCTP */
         ph.nl_head.ipv6.protocol = SCPSCTP;
         cks = checksum ((uint16_t *) & ph, 42);
         if (cks != 0xffff) {
             LOG ("Checkum failure \n");
             return (0);                /* Disregard on checksum failure */
         }
    }
  }


  chl = tp_Uncompress (s, cp);
  len -= chl;      /* Don't want the compressed header with data */

  tp_CommonHandler (s, rqts, &(s->in_th), (((byte *) tp) + chl), len);
  return (0);
}


// * Handler for incoming TP packets.
void tp_Handler (scps_np_rqts * rqts, int len, tp_Header * tp)
{
  tp_PseudoHeader ph;
  tp_Socket *s;
  int tp_header_len = 0;
  int odd_aligned = 0;
  char ugly[60];
  byte *data = NULL;
  int rc;

  int s1 = -1;
  int s2 = -1;
  struct sockaddr_in dst;
  struct sockaddr_in src;
  tp_Socket *active_s = NULL;
  int reset_now = 0;
  int close_s1 = 0;

  if (rqts->nl_protocol == NL_PROTOCOL_NP) {
        ph.nl_head.ipv4.src = htonl (rqts->ipv4_src_addr);
        ph.nl_head.ipv4.dst = htonl (rqts->ipv4_dst_addr);
        ph.nl_head.ipv4.mbz = 0;
                /* pseudo header checksum still assumes TP */
        ph.nl_head.ipv4.protocol = IPPROTO_TCP;
        ph.nl_head.ipv4.length = htons (len);
        ph.nl_head.ipv4.checksum = checksum ((uint16_t *) tp, ntohs (ph.nl_head.ipv4.length));
    if (checksum ((uint16_t *) & ph, 14) != 0xffff)
    {
      for (s = tp_allsocs; s; s = s->next)
        if (s->hisport != 0 &&
            tp->dstPort == s->myport &&
            tp->srcPort == s->hisport &&
            htonl (rqts->ipv4_src_addr) == s->his_ipv4_addr)
          {
            break;
          }
      LOG ("gateway: %s BAD CHECKSUM on seq num abs(%u) rel(%u) %u %x %x \n",
              "m(?) h(?)",
              (unsigned int) (htonl (tp->seqnum)),
              (unsigned int) (htonl (tp->seqnum)) - ((s) ? s->initial_seqnum
                                                     : 0),
              len,
              (unsigned int) rqts->ipv4_src_addr, (unsigned int) rqts->ipv4_dst_addr);
      return;
    }
  }
  if (rqts->nl_protocol == NL_PROTOCOL_IPV4) {
        ph.nl_head.ipv4.src = htonl (rqts->ipv4_src_addr);
        ph.nl_head.ipv4.dst = htonl (rqts->ipv4_dst_addr);
        ph.nl_head.ipv4.mbz = 0;
                /* pseudo header checksum still assumes TP */
        ph.nl_head.ipv4.protocol = IPPROTO_TCP;
        ph.nl_head.ipv4.length = htons (len);
        ph.nl_head.ipv4.checksum = checksum ((uint16_t *) tp, ntohs (ph.nl_head.ipv4.length));
  if (checksum ((uint16_t *) & ph, 14) != 0xffff)
    {
      for (s = tp_allsocs; s; s = s->next)
        if (s->hisport != 0 &&
            tp->dstPort == s->myport &&
            tp->srcPort == s->hisport &&
            htonl (rqts->ipv4_src_addr) == s->his_ipv4_addr)
          {
            break;
          }
      LOG ("gateway: %s BAD CHECKSUM on seq num abs(%u) rel(%u) %u %x %x \n",
              "m(?) h(?)",
              (unsigned int) (htonl (tp->seqnum)),
              (unsigned int) (htonl (tp->seqnum)) - ((s) ? s->initial_seqnum : 0),
              len,
              (unsigned int) rqts->ipv4_src_addr, (unsigned int) rqts->ipv4_dst_addr);
      return;
    }

  }

  if (rqts->nl_protocol == NL_PROTOCOL_IPV6) {
        hton16 (ph.nl_head.ipv6.src.s6_addr, rqts->ipv6_src_addr.s6_addr);
        hton16 (ph.nl_head.ipv6.dst.s6_addr, rqts->ipv6_dst_addr.s6_addr);

        memcpy (ph.nl_head.ipv6.src.s6_addr, rqts->ipv6_src_addr.s6_addr, 16);
        memcpy (ph.nl_head.ipv6.dst.s6_addr, rqts->ipv6_dst_addr.s6_addr, 16);

        ph.nl_head.ipv6.mbz1 = 0;
        ph.nl_head.ipv6.mbz2 = 0;
        ph.nl_head.ipv6.mbz3 = 0;
                /* pseudo header checksum still assumes TP */
        ph.nl_head.ipv6.protocol = IPPROTO_TCP;
        ph.nl_head.ipv6.length = htonl (((longword) len));
        ph.nl_head.ipv6.checksum = checksum ((uint16_t *) tp, len);
  if (checksum ((uint16_t *) & ph, 42) != 0xffff)
    {
      for (s = tp_allsocs; s; s = s->next)
        if (s->hisport != 0 &&
            tp->dstPort == s->myport &&
            tp->srcPort == s->hisport &&
            memcmp (&(rqts->ipv6_src_addr.s6_addr), &(s->his_ipv6_addr.s6_addr) , sizeof (struct in6_addr)))
          {
            break;
          }
      LOG ("gateway: %s BAD CHECKSUM on seq num abs(%u) rel(%u) %u %x %x \n",
              "m(?) h(?)",
              (unsigned int) (htonl (tp->seqnum)),
              (unsigned int) (htonl (tp->seqnum)) - ((s) ? s->initial_seqnum
                                                     : 0),
              len,
              (unsigned int) rqts->ipv4_src_addr, (unsigned int) rqts->ipv4_dst_addr);
      return;
    }

  }

  if ((long) tp & (sizeof (int) - 1))  /* must align xport hdr */
    {
      odd_aligned = 1;
      /* Reach in and get tp header length */
      tp_header_len = ((u_char) (*(((char *) tp) + 12)) & 0xF0) >> 2;
      memcpy (ugly, (char *) tp, tp_header_len);
      data = (byte *)((char *) tp + tp_header_len);
      tp = (tp_Header *) ugly;
    }
  /* demux to active sockets */

  for (s = tp_allsocs; s; s = s->next) {

   if ( ((rqts->nl_protocol == NL_PROTOCOL_NP) &&
         (s->nl_protocol_id == NL_PROTOCOL_NP)) ||
        ((rqts->nl_protocol == NL_PROTOCOL_IPV4) &&
         (s->nl_protocol_id == NL_PROTOCOL_IPV4))) {

    if (s->hisport != 0 && tp->dstPort == s->myport && tp->srcPort == s->hisport &&
      (htonl (rqts->ipv4_src_addr) == s->his_ipv4_addr))
      {
      break;
      }
    } 

    if ((rqts->nl_protocol == NL_PROTOCOL_IPV6) &&
       (s->nl_protocol_id == NL_PROTOCOL_IPV6)) {
      if (s->hisport != 0 &&
        tp->dstPort == s->myport &&
        tp->srcPort == s->hisport &&
        (!memcmp (&(rqts->ipv6_src_addr.s6_addr), &(s->his_ipv6_addr.s6_addr), sizeof (struct in6_addr))))   {
          break;
        }
    }
  }

  if (s == NULL)
    {

      /* demux to passive sockets */

      for (s = tp_allsocs; s; s = s->next)
        {
          if (((s->hisport == 0) && (tp->dstPort == s->myport))
        && (!memcmp (&(rqts->ipv6_dst_addr), &(s->my_ipv6_addr), sizeof (struct in6_addr)))
            )
            {
              break;
            }
        }
    }

  if (s == NULL)
    {

      /* demux to passive sockets */

      for (s = tp_allsocs; s; s = s->next)
  {
    if (((s->hisport == 0) && (tp->dstPort == s->myport))
        && (htonl (rqts->ipv4_dst_addr) == s->my_ipv4_addr)
      )
      {
        break;
      }
  }
    }

  if ((s) && (s->Initialized == 0))
    {
      LOG ("Demuxed to an initialized socket %p %d\n", s, s->state);
      fflush (stdout);
    }


  if (s == NULL) {
    if (tp->flags & tp_FlagRST) {
      return;
    }

    if ((!(tp->flags & tp_FlagSYN)) || (tp->flags & tp_FlagACK)) {
      reset_now = 1;
    }
    if ((sys_memory.clust_in_use  + 20  > sys_memory.fclist.max_size) || (reset_now) ) {
      LOG ("Gateway: Connection being reset %d %d %d\n", 20, sys_memory.clust_promised, sys_memory.fclist.max_size);
      cluster_check = 0;
      if ((s1 = scps_socket (AF_INET, SOCK_STREAM, 0)) == -1) {
        cluster_check = 1;
        return;
      }

      s = (tp_Socket *) scheduler.sockets[s1].ptr;
      s->ph.nl_head.ipv4.src = htonl (rqts->ipv4_dst_addr);
      s->ph.nl_head.ipv4.dst = htonl (rqts->ipv4_src_addr);

      memset ((char *) &dst, 0, sizeof (dst));
      dst.sin_family = AF_INET;
      dst.sin_addr.s_addr = htonl (rqts->ipv4_dst_addr);
      dst.sin_port = tp->dstPort;

      if ((rc = scps_bind (s1, (struct sockaddr *) &dst, sizeof (dst))) == -1) {
        scps_close (s1);
        cluster_check = 1;
        return;
      }

      memcpy (&(s->his_ipv4_addr), &(rqts->ipv4_src_addr), sizeof (u_long));
      memcpy (&(s->hisport), &(tp->srcPort), sizeof (u_short));

      memcpy (&(s->src_mac_addr [0]), &(rqts->dst_mac_addr [0]),6);
      memcpy (&(s->dst_mac_addr [0]), &(rqts->src_mac_addr [0]),6);

      s->frame_type = rqts->frame_type;
      s->recv_tap_if = rqts->recv_tap_if;

      gateway_reset (s1, rqts, tp);
      cluster_check = 1;
      return;
    }

    memset ((char *) &dst, 0, sizeof (dst));
    dst.sin_family = AF_INET;
    dst.sin_addr.s_addr = htonl (rqts->ipv4_dst_addr);
    dst.sin_port = tp->dstPort;

    if ((s1 = scps_socket (AF_INET, SOCK_STREAM, 0)) == -1) {
      LOG ("Gateway: not allowing any more connection ss1\n");
      return;
    }

    s = (tp_Socket *) scheduler.sockets[s1].ptr;
    s->ph.nl_head.ipv4.src = htonl (rqts->ipv4_dst_addr);
    if ((rc = scps_bind (s1, (struct sockaddr *) &dst, sizeof (dst))) == -1) {
      LOG("Gateway: not allowing any more connection sb1\n");
      scps_close (s1);
      return;
    }

    memcpy (&(s->src_mac_addr [0]), &(rqts->dst_mac_addr [0]),6);
    memcpy (&(s->dst_mac_addr [0]), &(rqts->src_mac_addr [0]),6);
    s->frame_type = rqts->frame_type;
    s->recv_tap_if = rqts->recv_tap_if;

    s->DSCP = rqts->DSCP; 
    s->np_rqts.DSCP = rqts->DSCP;


    tp_mss (s, 0);    /* provisional mss setup */
    gateway_set_options (s->sockid, rqts->divert_port_number, 0);
    s->state_prev = tp_StateCLOSED;  /* Might have been tp_StateNASCENT */
    s->state = tp_StateLISTEN;

    s->timeout = 0x7ffffff;  /* forever... */
    s->hisport = 0;
    s->ph.nl_head.ipv4.dst = 0;
    s->link_outage = 0;  /* forced for now */

/* Now create active socket */
    if (!reset_now) {
      int initial_port;
      memset ((char *) &src, 0, sizeof (src));
      src.sin_family = AF_INET;
      src.sin_addr.s_addr = htonl (rqts->ipv4_src_addr);
      initial_port = tp->srcPort;
      src.sin_port = initial_port;
      if ((s2 = scps_socket (AF_INET, SOCK_STREAM, 0)) == -1){
        LOG ("Gateway: not allowing any more connection ss2\n");
        reset_now = 1;
      } else {
        active_s = (tp_Socket *) scheduler.sockets[s2].ptr;
        active_s->ph.nl_head.ipv4.src = htonl (rqts->ipv4_src_addr);
        if ((rc = scps_bind (s2, (struct sockaddr *) &src, sizeof(src))) == -1) {
          LOG ("Gateway: not allowing any more connection sb2\n");
          close_s1 = 1;
          scps_close (active_s->sockid);
        }
        active_s->np_rqts.ipv4_src_addr = htonl (rqts->ipv4_src_addr);
        gateway_set_options (active_s->sockid, rqts->divert_port_number, 1);
        memcpy (&(active_s->src_mac_addr [0]), &(rqts->src_mac_addr [0]),6);
        memcpy (&(active_s->dst_mac_addr [0]), &(rqts->dst_mac_addr [0]),6);
        active_s->frame_type = rqts->frame_type;
        active_s->recv_tap_if = rqts->peer_tap_if;
        s->DSCP = rqts->DSCP; 
        active_s->DSCP = rqts->DSCP;
        active_s->np_rqts.DSCP = rqts->DSCP;
      }
    }

    /* Now connect the two sockets */
    if ((!reset_now) && (!close_s1)) {
      s->peer_socket = (tp_Socket *) active_s;
      s->gateway_flags |= GATEWAY_PEER_WIN_NOT_OPENED;
      active_s->peer_socket = (tp_Socket *) s;
      s->gateway_flags |= GATEWAY_SEND_SYN;
    } else {
      if (close_s1) {
        LOG ("Gateway: closing s1 - not enough resoures\n");
        scps_close (s1);
      }
      if (reset_now) {
        LOG ("Gateway: Reseting s1 - not enough resources\n");
        gateway_reset (s1, rqts, tp);
      }
      return;
    }

    /* Now do the accept which should just come naturally */
    gateway_double_check_parameters (s);
    gateway_double_check_parameters (active_s);
  } else {
    memcpy (&(s->np_rqts.src_mac_addr [0]), &(rqts->dst_mac_addr [0]),6);
    memcpy (&(s->np_rqts.dst_mac_addr [0]), &(rqts->src_mac_addr [0]),6);
  }

  if (odd_aligned){
    memcpy (&(s->in_th), ugly, tp_header_len);
    tp = (tp_Header *) & (s->in_th);
  } else {
    tp_header_len = tp->th_off << 2;
    data = ((byte *) tp + tp_header_len);
  }

  if (s->capabilities & CAP_COMPRESS)
    memcpy ((tp_Header *) & s->in_th, tp, ((tp->flags & tp_FlagDO) >> 10));
  len -= tp_header_len;

/*
 * If you receive packets from a partcular route, the make sure the
 * interface is set to AVAILABLE.  This may cause problems when the
 * forward and return link are independent of each other.  - PDF
 */
  if (s->rt_route) 
    s->rt_route->flags |= RT_LINK_AVAIL;

  if (s->state == tp_StateCLOSED){
    gateway_reset (s->sockid, rqts, tp);
    return;
  }

  if (s->DSCP != rqts ->DSCP) {
    s->DSCP = rqts->DSCP; 
  }

  if ((s->peer_socket) && (s->peer_socket->DSCP != rqts ->DSCP)) {
    s->peer_socket->DSCP = rqts->DSCP; 
  }

  rc = tp_CommonHandler (s, rqts, tp, data, len);
  switch (rc)
    {
    case 0:
      scps_close (s1);
      scps_close (s2);
      break;

    case -2:
      tp_Abort (s1);
      tp_Abort (s2);
      break;

    case -1:
      break;

    default:
      if ((s->gateway_flags & GATEWAY_SEND_SYN)  && (s2 > 0)) {
        s->gateway_flags &= (~GATEWAY_SEND_SYN);
        SET_ERR (0);
        rc = tp_Connect (s2, (void *) &dst, sizeof (dst));
        if ((rc == -1) && (GET_ERR () != SCPS_EINPROGRESS)) {
          /* If you can complete the connection you must abort */
          tp_Abort (s1);
          tp_Abort (s2);
    
          return;
        }

        if ((s) && (active_s)) {
          route *tmp = active_s->peer_socket->rt_route;
 
          if (active_s->peer_socket->DSCP != rqts ->DSCP) {
              active_s->peer_socket->DSCP = rqts->DSCP; 
          }
          if (!(active_s->peer_socket->rt_route = route_rt_lookup_s (active_s->peer_socket))) {
            active_s->peer_socket->rt_route = tmp;
          }

          tmp = active_s->rt_route;
 
          if (active_s->DSCP != rqts ->DSCP) {
              active_s->DSCP = rqts->DSCP; 
          }
          if (!(active_s->rt_route = route_rt_lookup_s (active_s))) {
              active_s->rt_route = tmp;
        }
      }
    }
    break;
  }
}


int tp_CommonHandler (tp_Socket * s, scps_np_rqts * rqts, tp_Header * tp, byte * data, int len)
{
  uint16_t flags;
  struct mbuff *mbuffer;
  short option_len;
  int ts_present;
  uint32_t ts_val, ts_ecr, temp, temp1;
  uint32_t tempseq;
  tp_Socket *new_socket = NULL;
  tp_Socket *iterative_socket = NULL;
  unsigned int mss;
  struct timeval mytime;
  volatile uint32_t flippedwindow = ntohs (tp->window);
  volatile uint32_t flippedack = ntohl (tp->acknum);
  volatile uint32_t flippedseq = ntohl (tp->seqnum);

#ifndef LINUX_STYLE_FIRST_DATA_RTO
  uint32_t temp2;
#endif /* LINUX_STYLE_FIRST_DATA_RTO */
  int does_a_peer_exist = (int) (s->peer_socket != NULL);
  tp_Socket *listening_s = NULL;
  mytime.tv_sec = mytime.tv_usec = 0;

  if ((len != 0) && (sys_memory.clust_in_use + 10 >= sys_memory.fclist.max_size)) {
     return (-1);
  }

  flags = tp->flags;
  if (flags & tp_FlagRST)
    {
      tp_Socket *peer_s;
      peer_s = s->peer_socket;

      if ((s->state == tp_StateCLOSED) /* || (s->state == tp_StateTIMEWT) */ )
  {
    return (0);
  }

      s->state_prev = s->state;
      s->state = tp_StateCLOSED;
       clear_timer (s->otimers[Rexmit], 1);
      SET_ERR (SCPS_ECONNRESET);
      if ((s->thread->status == Blocked) &&
    ((s->read) || (s->write)))
  {
    s->thread->status = Ready;
    scheduler.num_runable++;
    s->read = s->write = 0;
  }

      /* Write connection data to routing structure */
      if ( (peer_s) && (peer_s->peer_socket->peer_socket == peer_s) )
  {
    tp_Abort (peer_s->sockid);
  }
      tp_Unthread (s);
      return (-1);
    }

  if ((flags & tp_FlagSYN) == 0)
    s->snd_awnd = flippedwindow << s->snd_scale;
  else
    s->snd_awnd = flippedwindow;

  if (!(s->capabilities & CAP_CONGEST))
    s->snd_cwnd = s->snd_awnd;

  s->sndwin = min (s->snd_cwnd, s->snd_awnd + s->snduna - s->max_seqsent);

  ts_present = 0;

  option_len = (tp->th_off << 2) - 20;

  if ((len) && (!s->peer_socket) ) {
  gateway_reset (s->sockid, rqts, tp);
  }

  if (option_len && (s->state != tp_StateLISTEN))
    tp_dooptions (s, option_len, tp, &ts_present, &ts_val, &ts_ecr);

  tp_now = clock_ValueRough ();

  if (s->capabilities & CAP_TIMESTAMP)
    {
      /* Revert to Braden code */
      if (ts_present && SEQ_GEQ (ts_val, s->ts_recent) &&
    SEQ_LEQ (flippedseq, s->lastack))
  {
    s->ts_recent_age = tp_now;
    s->ts_recent = ts_val;
    s->ts_now = ts_val;
  }
      else
  {
    if (ts_present && SEQ_GEQ (ts_val, s->ts_now)) {
      s->ts_now = ts_val;
    }
  }
      if (ts_present && ts_ecr)
  {
    temp = (uint32_t) ((abs) (tp_now - ts_ecr));
    /* tp_xmit_timer (s, temp, temp); */
          if (SEQ_GT (flippedack, s->snduna)) {
    /* PDF -- only update rtt if acknum moves forward */
      tp_xmit_timer (s, temp, 0);
    }
  }
    }


  s->flags = tp_FlagACK;

  if (s->DSCP != rqts ->DSCP) {
         s->DSCP = rqts->DSCP; 
  }

         s->rt_route = route_rt_lookup_s (s);

  s->np_rqts.DSCP = rqts->DSCP;
  s->ip_templ.nl_head.ipv4.vht = htons (0x4500 | rqts->DSCP);
  s->DSCP = rqts->DSCP; 
  s->protocol_id = rqts->tpid; 

  if (s->peer_socket) {
      s->peer_socket->ip_templ.nl_head.ipv4.vht = htons (0x4500 | rqts->DSCP);
  }

  switch (s->state)
    {        /* Switch */

    case tp_StateLISTEN:
      {
  if (flags & tp_FlagSYN)
    {
    NewConnect:
      if (!(new_socket = clone_socket (s)))
        {
                tp_Socket *peer_s = s->peer_socket;
          gateway_reset (s->sockid, rqts, tp);
    if (peer_s) {
      tp_Abort (peer_s->sockid);
    }
    return (-2);
        }

            s->hisport = ntohs (tp->srcPort);

      if (does_a_peer_exist)
        {
    s->peer_socket->peer_socket = new_socket;
    new_socket->peer_socket = s->peer_socket;
        }
      /* This doesn't check for ports already in use, Danger! */
      new_socket->initial_seqnum_rec = flippedseq;
      new_socket->acknum = flippedseq + 1;
      new_socket->lastuwein = new_socket->seqnum + flippedwindow;
      new_socket->hisport = tp->srcPort;
            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4: 
                        new_socket->his_ipv4_addr = htonl (rqts->ipv4_src_addr); //  
                        break;  
                case NL_PROTOCOL_NP:
                        new_socket->his_ipv4_addr = htonl (rqts->ipv4_src_addr); //  
                        break;  
                case NL_PROTOCOL_IPV6:
                        hton16 (new_socket->his_ipv6_addr.s6_addr, rqts->ipv6_src_addr.s6_addr);
                        break;  
           }  
      new_socket->my_ipv4_addr = htonl (rqts->ipv4_dst_addr);

            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4: 
                        new_socket->ip_templ.nl_head.ipv4.source = htonl (rqts->ipv4_dst_addr);
                        new_socket->my_ipv4_addr = htonl (rqts->ipv4_dst_addr);
                        break;  
                case NL_PROTOCOL_NP:
                        new_socket->np_templ.src_npaddr = htonl (rqts->ipv4_dst_addr); 
                        new_socket->my_ipv4_addr = htonl (rqts->ipv4_dst_addr);
                        break;
                case NL_PROTOCOL_IPV6:
                        hton16 (new_socket->ip_templ.nl_head.ipv6.src.s6_addr, rqts->ipv6_dst_addr.s6_addr);
                        hton16 (new_socket->my_ipv6_addr.s6_addr, rqts->ipv6_dst_addr.s6_addr);
                        break;
            }

            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4:
                case NL_PROTOCOL_NP:
                        new_socket->ph.nl_head.ipv4.dst = new_socket->his_ipv4_addr;
                        break;
                case NL_PROTOCOL_IPV6:
                        memcpy (&(new_socket->ph.nl_head.ipv6.dst), &(new_socket->his_ipv6_addr),16);
                        break;
            }

      if (new_socket->capabilities & CAP_BETS)
        new_socket->BETS.InRecSeq = new_socket->acknum - 1;
      /* Add checks to make sure that the mbuffer isn't underrun */
      new_socket->sh_off = new_socket->th_off -
        new_socket->sp_size - (new_socket->sp_size % sizeof (uint32_t));
      new_socket->nh_off = new_socket->sh_off -
        new_socket->np_size - (new_socket->np_size % sizeof (uint32_t));

      new_socket->flags = tp_FlagSYN | tp_FlagACK;
      new_socket->lastack = new_socket->acknum;

      new_socket->lastuwe = new_socket->acknum + new_socket->rcvwin;

      new_socket->np_rqts.tpid = IPPROTO_TCP;
            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4:
                case NL_PROTOCOL_NP:
                        new_socket->np_rqts.ipv4_dst_addr = rqts->ipv4_src_addr;
                        break;
                case NL_PROTOCOL_IPV6:
                        memcpy (&(new_socket->np_rqts.ipv6_dst_addr.s6_addr), &(rqts->ipv6_src_addr.s6_addr), 16);
                        break;
            }
            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4:
                case NL_PROTOCOL_NP:
                        new_socket->np_rqts.ipv4_src_addr = rqts->ipv4_dst_addr;
                        break;
                case NL_PROTOCOL_IPV6:
                        memcpy (&(new_socket->np_rqts.ipv6_src_addr.s6_addr), &(rqts->ipv6_dst_addr.s6_addr), 16);
                        break;
            }
      new_socket->np_rqts.timestamp.format = 0;
      new_socket->np_rqts.timestamp.ts_val[0] =
        new_socket->np_rqts.timestamp.ts_val[1] = 0;
      new_socket->np_rqts.bqos.precedence = rqts->bqos.precedence;
      new_socket->np_rqts.bqos.routing = 0;
      new_socket->np_rqts.bqos.pro_specific = 0;
      new_socket->np_rqts.eqos.ip_precedence = 0;
      new_socket->np_rqts.eqos.ip_tos = 0;
      new_socket->np_rqts.cksum = 1;  /* rqts->cksum; */
      new_socket->np_rqts.int_del = 0;

            if ((rqts->nl_protocol == NL_PROTOCOL_IPV4) ||
                (rqts->nl_protocol == NL_PROTOCOL_IPV6) ||
                (rqts->nl_protocol == NL_PROTOCOL_NP)) {
                new_socket->np_rqts.nl_protocol = rqts->nl_protocol;
            }  

      new_socket->sp_size = 0;
      new_socket->np_size = np_hdr_size (new_socket->np_rqts);

            tp_dooptions (new_socket, option_len, tp, &ts_present, &ts_val,
                          &ts_ecr);
            
            switch (new_socket->np_rqts.nl_protocol) {
                case NL_PROTOCOL_IPV4:
                        new_socket->np_size = ip_get_template (&(new_socket->np_rqts), &(new_socket->ip_templ));
                        break;
                case NL_PROTOCOL_NP:
                        new_socket->np_size = scps_np_get_template (&(new_socket->np_rqts),&(new_socket->np_templ));
                        break;
            }


      if ((mbuffer = tp_BuildHdr (new_socket, NULL, 0)))
        enq_mbuff (mbuffer, new_socket->send_buff);

      if (!(new_socket->send_buff->send))
        new_socket->send_buff->send = new_socket->send_buff->last;

      if (new_socket->send_buff->send)
        {
    tp_NewSend (new_socket, NULL, FALSE);
        }

      new_socket->state_prev = new_socket->state;
      new_socket->state = tp_StateSYNREC;
       new_socket->timeout = s->LONGTIMEOUT;

      /* Now, attach new_socket to s->q0 */
      new_socket->qhead = s;
      new_socket->q0 = (s->q0);

      if (s->q0)
        s->q0->q = new_socket;

      s->q0 = new_socket;
      new_socket->q = NULL;

      if (new_socket->capabilities & CAP_JUMBO)
        {
    new_socket->gateway_flags |= (GATEWAY_SCPS_TP_SESSION);
        } else {
                new_socket->capabilities |= CAP_CONGEST;
                new_socket->cong_algorithm = VJ_CONGESTION_CONTROL;
              }

/* The listening socket should be closed after the connection has been fully
 * established */
    }
      }
      break;

    case tp_StateSYNSENT:
      {
  if (flags & tp_FlagSYN)
    {
      s->acknum++;
      s->timeout = s->TIMEOUT;

      if ((s->state_prev == tp_StateCLOSED) && (flags & tp_FlagACK)
    && (flippedack == (s->snduna + 1)))
        {
    /* Cool, this is a SYN,ACK in response to our active open... */
    clear_timer (s->otimers[Rexmit], 1);

                mytime.tv_usec = 0;
                mytime.tv_sec = 1;  /* Initially I want to send an ACK fairly soon
                incase the ACK that opens up the window gets
                lost -- PDF */
          
                set_timer (&mytime, s->otimers[KA], 1);

          s->initial_seqnum_rec = flippedseq;
    s->state_prev = s->state;
    s->state = tp_StateESTAB;
     s->sockFlags &= ~SOCK_ACKNOW;
    /* We have an open connection, make the socket as writeable */
    ADD_WRITE (s);
    if ((s->thread->status == Blocked) && (s->write))
      {
        /*
         * If this socket is not currently on the list
         * of *writeable* sockets, place it there.
         */
        ADD_WRITE (s);
        s->write = 0;


        /*
         * Remove this socket from the list of readable
         * sockets if it is there.
         */

        if (s->read_parent)
          {
      if (s->read_prev)
        s->read_prev->read_next = s->read_next;
      else if ((tp_Socket *) (s->thread->read_socks) ==
         (tp_Socket *) s)
        ((tp_Socket *) s)->thread->read_socks = ((tp_Socket *) s->read_next);
      else
        LOG ("Uh oh! tp_handler.c:Common_Handler\n");

      if (s->read_next)
        s->read_next->read_prev = s->read_prev;
          }

        /* s->thread->read_socks &= ~(1 << s->sockid); */

        s->thread->status = Ready;
        scheduler.num_runable++;
      }

    s->snduna++;
    s->ack_delay = 0;
    s->acknum = flippedseq + 1;
    s->lastack = s->acknum;

    s->lastuwe = s->acknum + s->rcvwin;
    /* free the SYN's mbuffer */
    ts_val = mb_trim (s->send_buff, (s->snduna) - 1,
          &temp1, (uint32_t *) NULL);
    /*
     * If we are acked up, we can optionally reset the retransmission timer
     * values to their initial values (a la linux 2.0.32 kernel).  We
     * don't care if s->rtt is set or not (retransmitted SYN?)
     */
#ifndef LINUX_STYLE_FIRST_DATA_RTO
    if ((s->rtt) && (SEQ_GEQ (flippedack, s->rtseq)))
      {
        temp1 = (temp1) ? (uint32_t) ((abs) (tp_now - temp1)) : 0;
        temp2 = (ts_val) ? (uint32_t) ((abs) (tp_now -
                ts_val)) : 0;
        tp_xmit_timer (s, temp1, temp2);  /*SYN */
        s->rtt = 0;
      }
#else /* LINUX_STYLE_FIRST_DATA_RTO */
    if ( SEQ_GEQ (flippedack, s->rtseq) )
      {
        s->t_srtt = s->rt_route->rtt << (TP_RTT_SHIFT);
        s->t_rttvar = s->rt_route->rtt_var << TP_RTTVAR_SHIFT;
        s->t_rxtcur = s->rt_route->initial_RTO << TP_RTT_SHIFT;
        s->rtt = 0;
      }
#endif /* LINUX_STYLE_FIRST_DATA_RTO */


    if (s->capabilities & CAP_JUMBO)
      {
        s->gateway_flags |= (GATEWAY_SCPS_TP_SESSION);
      } else {
                    s->capabilities |= CAP_CONGEST;
                    s->cong_algorithm = VJ_CONGESTION_CONTROL;
                  }

    if ((ntohs (tp->window)) && (does_a_peer_exist))
      {
                    if (s->peer_socket) {
          s->peer_socket->gateway_flags &= (~GATEWAY_PEER_WIN_NOT_OPENED);
          s->peer_socket->sockFlags |= SOCK_ACKNOW;
                    }
      }
    if ((s->thread->status == Blocked) &&
        (((s->write) &&
          ((s->send_buff->max_size - (s->seqnum - s->snduna)) >=
           s->write))))
      {
        s->thread->status = Ready;
        scheduler.num_runable++;
        s->write = 0;
      }

    if ((s->sockFlags & (TF_RCVD_SCALE | TF_REQ_SCALE)) ==
        (TF_RCVD_SCALE | TF_REQ_SCALE))
      {
        s->snd_scale = s->requested_s_scale;
        s->rcv_scale = s->request_r_scale;
      }
    s->snd_awnd = flippedwindow << s->snd_scale;

    s->lastuwein = flippedack + s->snd_awnd;

    if (!(s->capabilities & CAP_CONGEST))
      s->snd_cwnd = s->snd_awnd;

    s->sndwin =
      min (s->snd_cwnd, s->snd_awnd + s->snduna - s->max_seqsent);

    /* build an ACK in an mbuffer and send it.
     * This logic is not quite right, since we
     * declare the connection open possibly
     * without having sent this ACK
     */

    if (s->capabilities & CAP_COMPRESS)
      {
        s->sockFlags |= SOCK_ACKNOW;
        gettimeofday (&(s->start_time), NULL);
      }
    if ((mbuffer = tp_BuildHdr (s, NULL, 0)))
      {
        if (s->capabilities & CAP_COMPRESS)
          {
      tp_NewSend (s, mbuffer, TRUE);
          }
        else
          {
      tp_NewSend (s, mbuffer, FALSE);
          }
        free_mbuff (mbuffer);
        gettimeofday (&(s->start_time), NULL);
      }
        }

      /*
       *  Not quite correct protection against old duplicate SYNs:
       * We have sent a SYN, To get to this point, we have sent a 
       * SYN and received a SYN but the acknum on the incoming SYN 
       * is wrong... Neglecting simultaneous opens, we should be 
       * sending a RST here and remaining in the SYNSENT state.
       *
       * We need to check our state prior to this, if it was CLOSED:
       *     If this packet is a pure SYN we have a simultaneous open. 
       *         Handle it.
       *     If this packet is a SYN,ACK but has an ACK < seqsent, 
       *         it is a old duplicate, send a reset and kill it!
       */

      else
        {
    /* Figure out why we are here... */
    if ((s->state_prev == tp_StateCLOSED))
      {
        if (!(flags & tp_FlagACK))
          {
      /* Simultaneous open... handle it; */
          }
        else if (SEQ_LT (flippedack, (s->snduna + 1)))
          {
      /* Old duplicate SYN,ACK - send a RST */
      s->flags = tp_FlagRST | tp_FlagACK;
      if ((mbuffer = tp_BuildHdr (s, NULL, 0)))
        {
          /* 
           * Need to doctor the sequence number of 
           * the packet in the mbuffer to be that 
           * in the incoming acknumber...
           */
          tempseq = s->max_seqsent;
          s->max_seqsent = flippedack;
          tp_NewSend (s, mbuffer, TRUE);
          s->max_seqsent = tempseq;
          free_mbuff (mbuffer);
        }
          }
        else
          {
      /* 
       * What could this be... a SYN,ACK with an 
       * acknum > s->max_seqsent... 
       *
       * Roll into above by sending a RST (but if this 
       * case is valid, someone is very broken on 
       * the other-side! 
       */
          }
      }
    else
      {
        /* This was a passive open to begin with...  */
      }
        }

      s->maxdata = s->maxseg - TP_HDR_LEN;

            if (s->rt_route->SMTU) {
                s->maxdata = min (s->maxdata, s->rt_route->SMTU - tp_hdr_size () - s->np_size - s->sp_size - TP_HDR_LEN);
            }



#ifdef INIT_CWND_INCR
      s->snd_cwnd = s->snd_prevcwnd =
        min (4 * s->maxdata, max (2 * s->maxdata, 4380));
#else /* INIT_CWND_INCR */
      s->snd_cwnd = s->snd_prevcwnd = s->maxdata;
#endif /* INIT_CWND_INCR */

#if SET_INITIAL_CWND
     s->snd_cwnd = s->snd_prevcwnd = SET_INITIAL_CWND;
#endif /* SET_INITIAL_CWND */

      s->sndwin =
        min (s->snd_cwnd, s->snd_awnd + s->snduna - s->max_seqsent);
    }
  if (flags & tp_FlagFIN)
    {
    return (-2);
    }
  if ( (s) && (s->peer_socket) )
    {
      gateway_move_data (s->peer_socket, s);
    }
  return (1);
      }
      break;

    case tp_StateSYNREC:
      {
  if (flags & tp_FlagSYN)
    {
      s->flags = tp_FlagSYN | tp_FlagACK;
      /* Just retransmit the original syn off the retransmission queue */
      tp_NewSend (s, s->send_buff->snd_una, TRUE);
    }

  if ((flags & tp_FlagACK) && (flippedack == s->seqnum))
    {
      if ((s->sockFlags & TF_COMPRESSING) == TF_COMPRESSING)
        {
    s->np_rqts.tpid = SCPSCTP;
                switch (s->np_rqts.nl_protocol) {
                        case NL_PROTOCOL_IPV4:
                                ip_get_template (&(s->np_rqts), &(s->ip_templ));
                                break;
                        case NL_PROTOCOL_NP:
                                s->np_size = scps_np_get_template (&(s->np_rqts), &(s->np_templ));
                                break;  
                }

        }
            s->maxdata = s->maxseg - TP_HDR_LEN;

            if (s->rt_route->SMTU) {
                s->maxdata = min (s->maxdata, s->rt_route->SMTU - tp_hdr_size () - s->np_size - s->sp_size - TP_HDR_LEN);
            }


      s->snd_cwnd = s->snd_prevcwnd = s->maxdata =
        s->maxseg - TP_HDR_LEN;

      mss = s->maxseg - TP_HDR_LEN;

#ifdef INIT_CWND_INCR
/* 
 * This is the Sally Floyd proposal for optionally increasing initial cwnd:
 *
 */
      s->snd_cwnd = s->snd_prevcwnd = min (4 * mss, max (2 * mss, 4380));
#else /* INIT_CWND_INCR */
      s->snd_cwnd = s->snd_prevcwnd = mss;
#endif /* INIT_CWND_INCR */

#if SET_INITIAL_CWND
     s->snd_cwnd = s->snd_prevcwnd = SET_INITIAL_CWND;
#endif /* SET_INITIAL_CWND */

      s->sndwin =
        min (s->snd_cwnd, s->snd_awnd + s->snduna - s->max_seqsent);

      s->state_prev = s->state;
      s->state = tp_StateESTAB;

            mytime.tv_usec = 0;
            mytime.tv_sec = 1;  /* Initially I want to send an ACK fairly soon
            incase the ACK that opens up the window gets
            lost -- PDF */
          
            set_timer (&mytime, s->otimers[KA], 1);

       s->snduna++;

      /* 
       * We now want to move this socket from the "connecting" to
       * the tail of the connected queue of the listening socket.
       */

      /* Disconnect from s->qhead->q0 */

            listening_s = (s->qhead);
      if (s->qhead->q0 == s)
        s->qhead->q0 = s->q0;

      /* Cut forward link */
      if (s->q0)
        s->q0->q = s->q;

      /* Cut reverse link */
      if (s->q)
        s->q->q0 = s->q0;

      s->q0 = s->q = NULL;

      /* Walk to the "end" of the connected queue */

      /* What the heck is this **really** doing??? */

      /*
       * If there is no current queue head, then
       * this newly connected socket becomes it.
       */

      if (!(s->qhead->q))
        {
    s->qhead->q = s;
    iterative_socket = s->qhead;
        }
      else
        /*
         * Otherwise, we want to add this socket to
         * chain of "child" sockets;
         *
         * Start at the parent's first entry (s->qhead->q)
         * and walk to the last socket in the "child" list;
         * When we hit the end of the list, we add the new
         * socket to the tail (iterative_socket->q = s)
         */
        {
    for (iterative_socket = s->qhead->q;
         ((iterative_socket) && (iterative_socket->q));
         iterative_socket = iterative_socket->q);
      /* Set previous list end's forward pointer to me. */
    iterative_socket->q = s;
    /* Set my reverse link to the previous list end (my
     * forward poitner (q) was nulled out above.
     */
    s->q0 = iterative_socket;
        }
      /*
       * This replaces the call to accept but doesn't commit suicide.
       */
      iterative_socket->q = NULL;
      if (s->qhead) {
        s->qhead = NULL;
        s->q = NULL;
        s->q0 = NULL;
      }

           if (listening_s) {
       scps_close (listening_s->sockid); 
           }
      // If this socket is not currently on the list of
      // writable sockets, place it there.
      ADD_WRITE (s);
      // If this socket is not currently on the
      // list of readable sockets, place it there.
      ADD_READ (s);

      if ((s->thread->status == Blocked) &&
    ((s->qhead->write) || (s->qhead->read)))
        {
    s->write = 0;
    s->thread->status = Ready;
    scheduler.num_runable++;
        }
      /* Free the mbuff associated with the SYN */
      ts_val = mb_trim (s->send_buff, (s->snduna), &temp1,
            (uint32_t *) NULL);

#ifndef LINUX_STYLE_FIRST_DATA_RTO
      if (((s->rtt) && (SEQ_GEQ (flippedack, s->rtseq))))
        {
    temp1 = (temp1) ? (uint32_t) ((abs) (tp_now - temp1)) : 0;
    temp2 = (ts_val) ? (uint32_t) ((abs) (tp_now - ts_val)) : 0;
    tp_xmit_timer (s, temp1, temp2); /* SYN */
    s->rtt = 0;
        }
#else /* LINUX_STYLE_FIRST_DATA_RTO */
      if ( SEQ_GEQ (flippedack, s->rtseq) )
        {
    s->t_srtt = s->rt_route->rtt << (TP_RTT_SHIFT);
    s->t_rttvar = s->rt_route->rtt_var << TP_RTTVAR_SHIFT;
    s->t_rxtcur = s->rt_route->initial_RTO << TP_RTT_SHIFT;
    s->rtt = 0;
        }
#endif /* LINUX_STYLE_FIRST_DATA_RTO */


      if ((s->sockFlags & (TF_RCVD_SCALE | TF_REQ_SCALE)) ==
    (TF_RCVD_SCALE | TF_REQ_SCALE))
        {
    s->snd_scale = s->requested_s_scale;
    s->rcv_scale = s->request_r_scale;
        }
      s->snd_awnd = flippedwindow << s->snd_scale;

      if (!(s->capabilities & CAP_CONGEST))
        s->snd_cwnd = s->snd_awnd;

      s->sndwin =
        min (s->snd_cwnd, (s->snd_awnd - (s->max_seqsent - s->snduna)));
      tp_ProcessData (s, tp, data, len);
      s->timeout = s->TIMEOUT;
      clear_timer (s->otimers[Rexmit], 1);

      gettimeofday (&(s->start_time), NULL);

      /* 
       * If there is any OutSeq data that was really in-order, bring
       * it into the fold now...
       */
      if ((s->Out_Seq->start) &&
    (s->Out_Seq->start->m_seq <= s->acknum))
        {

    mbuffer = deq_mbuff (s->Out_Seq);

    s->acknum += mbuffer->m_plen;

    /*
     * We've filled a hole, if there is another,
     * set the socket parameters accordingly.
     */

#ifdef OPT_SNACK1
    if (s->capabilities & CAP_SNACK)
      {
        if (s->Out_Seq->start)
          s->SNACK1_Flags |= SEND_SNACK1;
      }
#endif /* OPT_SNACK1 */

    s->app_rbuff->write_off += mbuffer->m_plen;

    /* Advance the write_head and offset properly */
    while (s->app_rbuff->write_off >= SMCLBYTES)
      {
        s->app_rbuff->write_off -= SMCLBYTES;
        s->app_rbuff->write_head->tail = SMCLBYTES;
        s->app_rbuff->write_head = s->app_rbuff->write_head->c_next;
        if (s->app_rbuff->bytes_beyond)
          s->app_rbuff->bytes_beyond -= SMCLBYTES;
      }
    if (s->app_rbuff->write_head)
      s->app_rbuff->write_head->tail = s->app_rbuff->write_off;

    s->app_rbuff->size += mbuffer->m_plen;

    if (s->app_rbuff->size > s->app_rbuff->biggest)
      s->app_rbuff->biggest = s->app_rbuff->size;

    s->app_rbuff->Out_Seq_size -= mbuffer->m_plen;

    enq_mbuff (mbuffer, s->receive_buff);
        }
      if ( (s) && (s->peer_socket) )
        {
    gateway_move_data (s->peer_socket, s);
        }
    }
  else
    /* Allow data to queue on a connecting connection... */
    {
      tp_ProcessData (s, tp, data, len);
    }
  return (1);
      }
      break;

    case tp_StateESTAB:
    case tp_StateCLOSEWT:  /* Eric is trying this 7/2/98 */
    case tp_StateFINWT1PEND:
    case tp_StateFINWTDETOUR:
    case tp_StateLASTACKPEND:
      {
  if ((flags & tp_FlagACK) == 0)
    {
      return (1);
    }

        if (s->peer_socket) {
          if ((flags & tp_FlagURG) && (ntohs (tp->urgentPointer))) {
            s->peer_socket->rel_seq_num_urg_ptr =
               flippedseq + ntohs (tp->urgentPointer) - s->initial_seqnum_rec;
            s->peer_socket->funct_flags =
               s->peer_socket->funct_flags | FUNCT_REL_SEQ_NUM_URG_PTR;
          }
     
          if ((s->peer_socket->funct_flags & FUNCT_REL_SEQ_NUM_URG_PTR) &&
              SEQ_GT (flippedseq,
                   s->peer_socket->rel_seq_num_urg_ptr+s->initial_seqnum_rec)) {
            s->peer_socket->rel_seq_num_urg_ptr = 0;
            s->peer_socket->funct_flags =
               s->peer_socket->funct_flags & (~FUNCT_REL_SEQ_NUM_URG_PTR);
          }
        }

  if (flags & tp_FlagSYN)  {
    /* Probably lost the ACK of the SYNACK */
    s->sockFlags |= SOCK_ACKNOW;
  }
  tp_ProcessAck (s, tp, len);
  if ((tp->flags & ~tp_FlagACK) || (len > 0))
    {
      /* if ((tp->flags & ~tp_FlagACK) || (len > (tp->th_off << 2))) */
      tp_ProcessData (s, tp, data, len);
    }
      }
      break;

    case tp_StateFINWT1:
      {
  if ((flags & tp_FlagACK) == 0)
    {
      return (-1);
    }

  tp_ProcessAck (s, tp, len);

  /* If other side acked our fin, move to FINWT2 */
  if (flippedack == s->seqnum)
    {
      s->state_prev = s->state;
      s->state = tp_StateFINWT2;
       clear_timer (s->otimers[Rexmit], 1);
      s->timeout = 0x7ffffff;
      (void) mb_trim (s->send_buff, s->seqnum, (uint32_t *) NULL,
          (uint32_t *) NULL);
      if ((s->thread->status == Blocked) &&
    ((s->read) || (s->write)))
        {
    s->thread->status = Ready;
    scheduler.num_runable++;
    s->read = s->write = 0;
        }

      clear_timer (s->otimers[Del_Ack], 1);
      s->sockFlags &= ~SOCK_DELACK;
            s->persist_shift = 0;
      s->maxpersist_ctr = 0;
      clear_timer (s->otimers[Persist], 1);
    }
  tp_ProcessData (s, tp, data, len);
      }
      break;

    case tp_StateFINWT2:
      {
  clear_timer (s->otimers[Del_Ack], 1);
  s->sockFlags &= ~SOCK_DELACK;
        s->persist_shift = 0;
  s->maxpersist_ctr = 0;
  clear_timer (s->otimers[Persist], 1);
  tp_ProcessAck (s, tp, len);
  tp_ProcessData (s, tp, data, len);
      }
      break;

    case tp_StateCLOSING:
      {
  if (flippedack == (s->seqnum))
    {
      s->state_prev = s->state;
      s->state = tp_StateTIMEWT;
            if (s->send_buff->holes) {
          s->send_buff->holes = 0x0;
            }
       s->timeout = s->TWOMSLTIMEOUT;
      mytime.tv_sec = s->TWOMSLTIMEOUT;
      mytime.tv_usec = 0;
      set_timer (&mytime, s->otimers[TW], 1);
      clear_timer (s->otimers[Rexmit], 1);
      tp_ProcessAck (s, tp, len);
    }
      }
      break;

    case tp_StateLASTACK:
      {
  clear_timer (s->otimers[Del_Ack], 1);
  s->sockFlags &= ~SOCK_DELACK;
        s->persist_shift = 0;
  s->maxpersist_ctr = 0;
  clear_timer (s->otimers[Persist], 1);

  if (flippedack == (s->seqnum))
    {
      s->state_prev = 0;
      s->state = tp_StateCLOSED;
       clear_timer (s->otimers[Rexmit], 1);
      if ((s->thread->status == Blocked) &&
    ((s->read) || (s->write)))
        {
    s->thread->status = Ready;
    scheduler.num_runable++;
    s->read = s->write = 0;
        }
      SET_ERR (SCPS_ENOTCONN);
 
      tp_Unthread (s);
      return (-1); /* PDF ADDED */
    }
      }
      break;

    case tp_StateTIMEWT:
      {
  /* 
   * If this is a SYN and the starting sequence number is greater 
   * than the final we've seen here, we are allowed to reincarnate 
   * this connection... See Stevens Vol2 fig 28.28; When listen forks
   * new sockets, this goto will go away... 
   */
  if ((flags & tp_FlagSYN) && (flippedseq > s->acknum))
    goto NewConnect;

  /* Otherwise, build a pure ack in an mbuffer and send it */
  s->lastack = s->acknum;

  s->lastuwe = s->acknum + s->rcvwin;

  if ((mbuffer = tp_BuildHdr (s, NULL, 0)))
    {
      tp_NewSend (s, mbuffer, FALSE);
      free_mbuff (mbuffer);
    }
      }
      break;
    }

  /* see if any changes to window size have allowed us to send */
  /* 
   * We should ONLY do this if we know we have data to push out,
   * Otherwise this is expensive!
   */
  return (1);
}

void gateway_reset (int s1, scps_np_rqts *rqts, tp_Header *tp)
{
  tp_Socket *s;

  s = (tp_Socket *) scheduler.sockets[s1].ptr;

  s->ph.nl_head.ipv4.dst = htonl (rqts->ipv4_src_addr);
  s->np_rqts.ipv4_dst_addr = (rqts->ipv4_src_addr);
  s->np_rqts.ipv4_src_addr = (rqts->ipv4_dst_addr);
  s->hisport = tp->srcPort;
  s->myport = tp->dstPort;
  s->np_rqts.tpid = IPPROTO_TCP;


  switch (s->np_rqts.nl_protocol) {
    case NL_PROTOCOL_IPV4:
      s->np_size = ip_get_template (&(s->np_rqts), &(s->ip_templ));
      break;
    case NL_PROTOCOL_NP:
      s->np_size = scps_np_get_template (&(s->np_rqts),&(s->np_templ));
      break; 
  }

  if (tp->flags & tp_FlagACK)
    {
      s->acknum = ntohl (tp->seqnum) + 0;
      s->seqsent = ntohl (tp->acknum) + 0;
      s->max_seqsent = ntohl (tp->acknum) + 0;
      s->seqnum = ntohl (tp->acknum) + 0;
    }
  else
    {
      s->acknum = ntohl (tp->seqnum) + 0;
      s->seqsent = 0;
      s->max_seqsent = 0;
      s->seqnum = 0;
    }

  {

    s->state = tp_StateESTAB;
    fflush (stdout);
    s->rt_route = def_route;
    tp_Abort (s1);
  }
}

void gateway_move_data (tp_Socket *from, tp_Socket *to)
{
  int can_be_read, can_be_written, to_be_moved, clusters;
  #define BUFFER_SIZ 8192
  unsigned char temp_buff[BUFFER_SIZ];
  int tmp = 0;
  int bytes_read;
  int temp = 0;

  from->gateway_flags &= ~GATEWAY_MORE_TO_WRITE;
  clusters = 0;

  if ((from ->peer_socket->peer_socket != from) || (to->peer_socket->peer_socket !=to)) {
  return;
  }

   if (sys_memory.clust_in_use + 10 >= sys_memory.fclist.max_size)
    {
      from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
      return;
    }

  if ((from && ((from->state == tp_StateESTAB) ||
       (from->state == tp_StateFINWT2) ||
       (from->state == tp_StateFINWT1PEND) ||
       (from->state == tp_StateCLOSEWT) ||
  /*       (from->state == tp_StateSYNREC) ||   */
       (from->state == tp_StateFINWT1))) &&
      (to && ((to->state == tp_StateESTAB) ||
       (to->state == tp_StateFINWT2) ||
       (to->state == tp_StateFINWT1PEND) ||
       (to->state == tp_StateCLOSEWT) ||
  /*      (to->state == tp_StateSYNREC) ||   */
       (to->state == tp_StateFINWT1))) &&
      (from->app_rbuff->size != 0))
    {

 
#define ORIG_CODE
#ifdef ORIG_CODE
      can_be_read = from->app_rbuff->size;
      can_be_written = to->app_sbuff->max_size -
  (to->app_sbuff->size + to->send_buff->data_size);
      to_be_moved = min (can_be_read, can_be_written);
      to_be_moved = min (to_be_moved, BUFFER_SIZ);


      if (to_be_moved < 1)
  {
    from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
    return;
  }

      if (to_be_moved < can_be_read)
        {
          from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
        }


      if (to->app_sbuff->write_head == NULL)
  {
    LOG ("Write head = 0\n");
    clusters++;

    if (to->app_sbuff->start == NULL)
      {
        LOG ("Chain Start = 0\n");
        clusters++;
      }
  }

      if (to->maxseg)
  temp = (to_be_moved / to->maxseg) + 1;

      while (((SMCLBYTES - to->app_sbuff->write_off) + to->app_sbuff->bytes_beyond)
       < (0 + to_be_moved + temp))
  {
    if (!((to->app_sbuff->num_elements < to->app_sbuff->max_elements)))
      {
        if (grow_chain (to->app_sbuff, 1))
    {
      from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
      return;
    }
      }
#ifdef ORIG_CODE
    if (!((to->app_sbuff->num_elements < to->app_sbuff->max_elements) &&
    (grow_chain (to->app_sbuff, 1))))
      {
        LOG ("error in growing chain in big while loop %d %d\n",
                       to->app_sbuff->num_elements, to->app_sbuff->max_elements);
        from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
        return;
      }
#endif /* ORIG_CODE */
  }


      if (grow_chain (to->app_sbuff, clusters))
  {
    if (to_be_moved)
      {
        bytes_read = scps_read (from->sockid, temp_buff, to_be_moved);
        if (bytes_read != to_be_moved)
    {
      LOG ("READ FAILED err(%d) to_be_moved(%d) bytes_read(%d) tmp(%d) from->state(%d)\n",
        GET_ERR (),
        to_be_moved,
        bytes_read,
        tmp,
        from->state);
      LOG ("  can_be_read(%d) can_be_written(%d) BUFFER_SIZE(%d)\n",
        can_be_read, can_be_written, BUFFER_SIZ);
  
      tmp = bytes_read;
      from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
    }
        else
    {
      tmp = scps_write (to->sockid, temp_buff, bytes_read);
      if (tmp != bytes_read)
        {
          LOG ("WRITE FAILED err(%d) bytes_read(%d) tmp(%d)\n", GET_ERR (),
            bytes_read, tmp);
        }
    }
      }
    else
      {
        from->gateway_flags |= GATEWAY_MORE_TO_WRITE;
      }

  }
      else
  {
    LOG("Could not grow chain %d \n", to->app_sbuff->max_elements);
  }
#endif /* ORIG_CODE */

    }
  if ( ((!from) || (from && ( ((from->state == tp_StateNASCENT ) || (from->state == tp_StateCLOSED) )
      || (!from->app_rbuff->size)))) && (to->gateway_flags & GATEWAY_SEND_FIN))
    {
      to->gateway_flags &= (~GATEWAY_SEND_FIN);
      tp_Close (to->sockid);
    }
  else
    {
    }
}


void gateway_set_options (int sockid, int divert_port, int other)
{
  int buffer_size = GATEWAY_DEFAULT_BUFFER;
  int one = 1;
  int zero = 0;
  tp_Socket *s;

  s = (tp_Socket *) scheduler.sockets[sockid].ptr;

  switch (other){
  case 0:
    /* This means the divert port corresponds to
     * the interface this was received on
     */
    s->divert_port = divert_port;
    if (divert_port == gw_ifs.a.divport) {
      s->gateway_lan_or_wan = gw_ifs.a.gateway_lan_or_wan;
      /* PDF SET the BUFFERS PROPERLY FIRST */
      if (gw_ifs.a.buf) {
        buffer_size = gw_ifs.a.buf;
      }
      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_SNDBUF, &buffer_size,
       sizeof buffer_size);

      if (gw_ifs.a.rbuf) {
        buffer_size = gw_ifs.a.rbuf;
      }

      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_RCVBUF, &buffer_size,
         sizeof buffer_size);

      /* SET THE CC NEXT */
      switch (gw_ifs.a.cc) {
      case NO_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_CONGEST,
             &zero, sizeof (zero));
        break;
      case VJ_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VJ_CONGEST,
             &one, sizeof (one));
        break;
      case VEGAS_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_CONGEST,
             &one, sizeof (one));
              if (gw_ifs.a.vegas_alpha)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA,
                     &gw_ifs.a.vegas_alpha, sizeof (gw_ifs.a.vegas_alpha));
              if (gw_ifs.a.vegas_beta)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_BETA,
                     &gw_ifs.a.vegas_beta, sizeof (gw_ifs.a.vegas_beta));
              if (gw_ifs.a.vegas_gamma)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA,
                     &gw_ifs.a.vegas_gamma, sizeof (gw_ifs.a.vegas_gamma));
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_SS,
               &gw_ifs.a.vegas_ss, sizeof (gw_ifs.a.vegas_ss));
        break;
      case FLOW_CONTROL_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_FLOW_CONTROL_CONGEST,
             &one, sizeof (one));
        break;
      }
      s->RTOMIN = gw_ifs.a.minrto;
      s->RTOMAX = gw_ifs.a.maxrto;
      s->TIMEOUT = gw_ifs.a.maxrto_ctr;
      s->LONGTIMEOUT = gw_ifs.a.maxrto_ctr;
      s->MAXPERSIST_CTR = gw_ifs.a.maxpersist_ctr;
      s->RTOPERSIST_MAX = gw_ifs.a.rtopersist_max;
      s->RTO_TO_PERSIST_CTR = gw_ifs.a.rto_to_persist_ctr;
      s->EMBARGO_FAST_RXMIT_CTR = gw_ifs.a.embargo_fast_rxmit_ctr;
      if (gw_ifs.a.ecbs1_len > 0 && gw_ifs.a.ecbs1_len < 20) {
        s->ecbs1 = gw_ifs.a.ecbs1;
        s->ecbs1_len = gw_ifs.a.ecbs1_len;
        memcpy (s->ecbs1_value, gw_ifs.a.ecbs1_value, s->ecbs1_len * 2);
      }
      if (gw_ifs.a.ecbs2_len > 0 && gw_ifs.a.ecbs2_len < 20) {
        s->ecbs2 = gw_ifs.a.ecbs2;
        s->ecbs2_len = gw_ifs.a.ecbs2_len;
        memcpy (s->ecbs2_value, gw_ifs.a.ecbs2_value, s->ecbs2_len * 2);
      }

      if (gw_ifs.a.msltimeout != 0) {
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT,
          &gw_ifs.a.msltimeout, sizeof (gw_ifs.a.msltimeout));
      }
      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_NLDEFAULT,
                            &gw_ifs.a.nl, sizeof (gw_ifs.a.nl));

      if (gw_ifs.a.ack_behave != -1) {
        short behave = gw_ifs.a.ack_behave;
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKBEHAVE,&behave, sizeof (behave));
      }

      if (gw_ifs.a.ack_delay != 0x0) {
         int ack_delay = gw_ifs.a.ack_delay;
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKDELAY,&ack_delay, sizeof (ack_delay));
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKFLOOR,&ack_delay, sizeof (ack_delay));
      }

      if (gw_ifs.a.ts == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_TIMESTAMP, &zero, sizeof (zero));
      if (gw_ifs.a.snack == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK, &zero, sizeof (zero));

      if (gw_ifs.a.nodelay == 1)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_NODELAY, &one, sizeof (one));
      if (gw_ifs.a.snack_delay != 0) {
         uint32_t snack_delay = gw_ifs.a.snack_delay;
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK_DELAY,&snack_delay, sizeof (snack_delay));
      }

      if (gw_ifs.a.tp_compress == 1)  
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_COMPRESS, &one, sizeof (one));
      if (gw_ifs.a.tcponly == 1)  
        s->capabilities &= (~CAP_JUMBO);

/* Assign the routed properly now */
      s->rt_route = def_route;
      s->rt_route_def = def_route;
    } else if (divert_port == gw_ifs.b.divport) {
      s->gateway_lan_or_wan = gw_ifs.b.gateway_lan_or_wan;
      if (gw_ifs.b.buf){
        buffer_size = gw_ifs.b.buf;
      }
      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_SNDBUF, &buffer_size, sizeof buffer_size);
      if (gw_ifs.b.rbuf) {
        buffer_size = gw_ifs.b.rbuf;
      }
      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_RCVBUF, &buffer_size,
         sizeof buffer_size);
      /* SET THE CC NEXT */
      switch (gw_ifs.b.cc) {
      case NO_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_CONGEST, &zero, sizeof (zero));
        break;
      case VJ_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VJ_CONGEST, &one, sizeof (one));
        break;
      case VEGAS_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_CONGEST,&one, sizeof (one));
              if (gw_ifs.b.vegas_alpha)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA,
                     &gw_ifs.b.vegas_alpha, sizeof (gw_ifs.b.vegas_alpha));
              if (gw_ifs.b.vegas_beta)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_BETA,
                     &gw_ifs.b.vegas_beta, sizeof (gw_ifs.b.vegas_beta));
              if (gw_ifs.b.vegas_gamma)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA,
                     &gw_ifs.b.vegas_gamma, sizeof (gw_ifs.b.vegas_gamma));
              scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_SS,
               &gw_ifs.b.vegas_ss, sizeof (gw_ifs.b.vegas_ss));
        break;
      case FLOW_CONTROL_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_FLOW_CONTROL_CONGEST,
             &one, sizeof (one));
        break;
      }
      s->RTOMIN = gw_ifs.b.minrto; 
      s->RTOMAX = gw_ifs.b.maxrto;
      s->TIMEOUT = gw_ifs.b.maxrto_ctr;
      s->LONGTIMEOUT = gw_ifs.b.maxrto_ctr;
      s->MAXPERSIST_CTR = gw_ifs.b.maxpersist_ctr;
      s->RTOPERSIST_MAX = gw_ifs.b.rtopersist_max;
      s->RTO_TO_PERSIST_CTR = gw_ifs.b.rto_to_persist_ctr;
      s->EMBARGO_FAST_RXMIT_CTR = gw_ifs.b.embargo_fast_rxmit_ctr;
 
      if (gw_ifs.b.ecbs1_len > 0 && gw_ifs.b.ecbs1_len < 20) {
        s->ecbs1 = gw_ifs.b.ecbs1;
        s->ecbs1_len = gw_ifs.b.ecbs1_len;
        memcpy (s->ecbs1_value, gw_ifs.b.ecbs1_value, s->ecbs1_len * 2);
      }

      if (gw_ifs.b.ecbs2_len > 0 && gw_ifs.b.ecbs2_len < 20) {
        s->ecbs2 = gw_ifs.b.ecbs2;
        s->ecbs2_len = gw_ifs.b.ecbs2_len;
        memcpy (s->ecbs2_value, gw_ifs.b.ecbs2_value, s->ecbs2_len * 2);
      }

      if (gw_ifs.b.msltimeout != 0) {
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT,
          &gw_ifs.b.msltimeout, sizeof (gw_ifs.b.msltimeout));
      }
      scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_NLDEFAULT, &gw_ifs.b.nl, sizeof (gw_ifs.b.nl));
      if (gw_ifs.b.ack_behave != -1) {
        short behave = gw_ifs.b.ack_behave;
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKBEHAVE, &behave, sizeof (behave));
      }
      if (gw_ifs.b.ack_delay != 0x0) {
        int ack_delay = gw_ifs.b.ack_delay;
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKDELAY, &ack_delay, sizeof (ack_delay));
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKFLOOR, &ack_delay, sizeof (ack_delay));
      }
      if (gw_ifs.b.tp_compress == 1)  
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_COMPRESS, &one, sizeof (one));

      if (gw_ifs.b.ts == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_TIMESTAMP, &zero, sizeof (zero));
      if (gw_ifs.b.snack == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK, &zero, sizeof (zero));
      if (gw_ifs.b.nodelay == 1)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_NODELAY, &one, sizeof (one));

      if (gw_ifs.b.snack_delay != 0) {
         uint32_t snack_delay = gw_ifs.b.snack_delay;
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK_DELAY,
             &snack_delay, sizeof (snack_delay));
      }
      if (gw_ifs.b.tcponly == 1)  
        s->capabilities &= (~CAP_JUMBO);
      /* Assign the routed properly now */
      s->rt_route = other_route;
      s->rt_route_def = other_route;
    }
    break;

    case 1:      
      /* This means the divert port corresponds to
       * the other interface this was received on
       */
    if (divert_port == gw_ifs.b.divport) {

    s->gateway_lan_or_wan = gw_ifs.a.gateway_lan_or_wan;
    s->divert_port = gw_ifs.a.divport;
    if (gw_ifs.a.buf)
      {
        buffer_size = gw_ifs.a.buf;
      }

    scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_SNDBUF, &buffer_size,
         sizeof buffer_size);

    if (gw_ifs.a.rbuf) {
        buffer_size = gw_ifs.a.rbuf;
    }

    scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_RCVBUF, &buffer_size,
         sizeof buffer_size);

    /* SET THE CC NEXT */
    switch (gw_ifs.a.cc)
      {
      case NO_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_CONGEST,
             &zero, sizeof (zero));
        break;
      case VJ_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VJ_CONGEST,
             &one, sizeof (one));
        break;
      case VEGAS_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_CONGEST,
             &one, sizeof (one));
              if (gw_ifs.a.vegas_alpha)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA,
                     &gw_ifs.a.vegas_alpha, sizeof (gw_ifs.a.vegas_alpha));
              if (gw_ifs.a.vegas_beta)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_BETA,
                     &gw_ifs.a.vegas_beta, sizeof (gw_ifs.a.vegas_beta));
              if (gw_ifs.a.vegas_gamma)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA,
                     &gw_ifs.a.vegas_gamma, sizeof (gw_ifs.a.vegas_gamma));
              scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_SS,
               &gw_ifs.a.vegas_ss, sizeof (gw_ifs.a.vegas_ss));
        break;
      case FLOW_CONTROL_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_FLOW_CONTROL_CONGEST,
             &one, sizeof (one));
        break;
      }



           s->RTOMIN = gw_ifs.a.minrto; 
           s->RTOMAX = gw_ifs.a.maxrto;
           s->TIMEOUT = gw_ifs.a.maxrto_ctr;
           s->LONGTIMEOUT = gw_ifs.a.maxrto_ctr;
           s->MAXPERSIST_CTR = gw_ifs.a.maxpersist_ctr;
           s->RTOPERSIST_MAX = gw_ifs.a.rtopersist_max;
           s->RTO_TO_PERSIST_CTR = gw_ifs.a.rto_to_persist_ctr;
     s->EMBARGO_FAST_RXMIT_CTR = gw_ifs.a.embargo_fast_rxmit_ctr;
               
           if (gw_ifs.a.ecbs1_len > 0 && gw_ifs.a.ecbs1_len < 20) {
        s->ecbs1 = gw_ifs.a.ecbs1;
        s->ecbs1_len = gw_ifs.a.ecbs1_len;
              memcpy (s->ecbs1_value, gw_ifs.a.ecbs1_value, s->ecbs1_len * 2);
           }

           if (gw_ifs.a.ecbs2_len > 0 && gw_ifs.a.ecbs2_len < 20) {
        s->ecbs2 = gw_ifs.a.ecbs2;
        s->ecbs2_len = gw_ifs.a.ecbs2_len;
              memcpy (s->ecbs2_value, gw_ifs.a.ecbs2_value, s->ecbs2_len * 2);
           }

           if (gw_ifs.a.msltimeout != 0) {
             scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT,
                            &gw_ifs.a.msltimeout, sizeof (gw_ifs.a.msltimeout));
     }

           scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_NLDEFAULT,
                            &gw_ifs.a.nl, sizeof (gw_ifs.a.nl));

            if (gw_ifs.a.ack_behave != -1) {
         short behave = gw_ifs.a.ack_behave;

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKBEHAVE,
             &behave, sizeof (behave));
      }

            if (gw_ifs.a.ack_delay != 0x0) {
         int ack_delay = gw_ifs.a.ack_delay;

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKDELAY,
             &ack_delay, sizeof (ack_delay));

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKFLOOR,
             &ack_delay, sizeof (ack_delay));
      }

      if (gw_ifs.a.tp_compress == 1)  
    scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_COMPRESS,
       &one, sizeof (one));

      if (gw_ifs.a.ts == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_TIMESTAMP,
             &zero, sizeof (zero));

      if (gw_ifs.a.snack == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK,
             &zero, sizeof (zero));

      if (gw_ifs.a.nodelay == 1)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_NODELAY,
             &one, sizeof (one));

      if (gw_ifs.a.snack_delay != 0) {
         uint32_t snack_delay = gw_ifs.a.snack_delay;
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK_DELAY,
             &snack_delay, sizeof (snack_delay));
      }

      if (gw_ifs.a.tcponly == 1)  
    s->capabilities &= (~CAP_JUMBO);

/* Assign the routed properly now */
          s->rt_route = def_route;
          s->rt_route_def = def_route;
  }
      else if (divert_port == gw_ifs.a.divport)
  {

    s->gateway_lan_or_wan = gw_ifs.b.gateway_lan_or_wan;
    s->divert_port = gw_ifs.b.divport;
    if (gw_ifs.b.buf)
      {
        buffer_size = gw_ifs.b.buf;
      }

    scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_SNDBUF, &buffer_size,
         sizeof buffer_size);

    if (gw_ifs.b.rbuf) {
        buffer_size = gw_ifs.b.rbuf;
    }

    scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_RCVBUF, &buffer_size,
         sizeof buffer_size);

    /* SET THE CC NEXT */
    switch (gw_ifs.b.cc)
      {
      case NO_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_CONGEST,
             &zero, sizeof (zero));
        break;
      case VJ_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VJ_CONGEST,
             &one, sizeof (one));
        break;
      case VEGAS_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_CONGEST,
             &one, sizeof (one));
              if (gw_ifs.b.vegas_alpha)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA,
                     &gw_ifs.b.vegas_alpha, sizeof (gw_ifs.b.vegas_alpha));
              if (gw_ifs.b.vegas_beta)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_BETA,
                     &gw_ifs.b.vegas_beta, sizeof (gw_ifs.b.vegas_beta));
              if (gw_ifs.b.vegas_gamma)  
            scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA,
                     &gw_ifs.b.vegas_gamma, sizeof (gw_ifs.b.vegas_gamma));
              scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_VEGAS_SS,
               &gw_ifs.b.vegas_ss, sizeof (gw_ifs.b.vegas_ss));
        break;
      case FLOW_CONTROL_CONGESTION_CONTROL:
        scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_FLOW_CONTROL_CONGEST,
             &one, sizeof (one));
        break;
      }



           s->RTOMIN = gw_ifs.b.minrto; 
           s->RTOMAX = gw_ifs.b.maxrto;
           s->TIMEOUT = gw_ifs.b.maxrto_ctr;
           s->LONGTIMEOUT = gw_ifs.b.maxrto_ctr;
           s->MAXPERSIST_CTR = gw_ifs.b.maxpersist_ctr;
           s->RTOPERSIST_MAX = gw_ifs.b.rtopersist_max;
           s->RTO_TO_PERSIST_CTR = gw_ifs.b.rto_to_persist_ctr;
     s->EMBARGO_FAST_RXMIT_CTR = gw_ifs.b.embargo_fast_rxmit_ctr;
               
           if (gw_ifs.b.ecbs1_len > 0 && gw_ifs.b.ecbs1_len < 20) {
        s->ecbs1 = gw_ifs.b.ecbs1;
        s->ecbs1_len = gw_ifs.b.ecbs1_len;
              memcpy (s->ecbs1_value, gw_ifs.b.ecbs1_value, s->ecbs1_len * 2);
           }

           if (gw_ifs.b.ecbs2_len > 0 && gw_ifs.b.ecbs2_len < 20) {
        s->ecbs2 = gw_ifs.b.ecbs2;
        s->ecbs2_len = gw_ifs.b.ecbs2_len;
              memcpy (s->ecbs2_value, gw_ifs.b.ecbs2_value, s->ecbs2_len * 2);
           }

           if (gw_ifs.b.msltimeout != 0) {
             scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT,
                            &gw_ifs.b.msltimeout, sizeof (gw_ifs.b.msltimeout));
     }

           scps_setsockopt (sockid, SCPS_SOCKET, SCPS_SO_NLDEFAULT,
                            &gw_ifs.b.nl, sizeof (gw_ifs.b.nl));

            if (gw_ifs.b.ack_behave != -1) {
         short behave = gw_ifs.b.ack_behave;

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKBEHAVE,
             &behave, sizeof (behave));
      }

            if (gw_ifs.b.ack_delay != 0x0) {
         int ack_delay = gw_ifs.b.ack_delay;

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKDELAY,
             &ack_delay, sizeof (ack_delay));

         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_ACKFLOOR,
             &ack_delay, sizeof (ack_delay));
      }

      if (gw_ifs.b.tp_compress == 1)  
    scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_COMPRESS,
       &one, sizeof (one));

      if (gw_ifs.b.ts == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_TIMESTAMP,
             &zero, sizeof (zero));

      if (gw_ifs.b.snack == 0)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK,
             &zero, sizeof (zero));

      if (gw_ifs.b.nodelay == 1)  
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_NODELAY,
             &one, sizeof (one));

      if (gw_ifs.b.snack_delay != 0) {
         uint32_t snack_delay = gw_ifs.b.snack_delay;
         scps_setsockopt (sockid, PROTO_SCPSTP, SCPSTP_SNACK_DELAY,
             &snack_delay, sizeof (snack_delay));
      }

      if (gw_ifs.b.tcponly == 1)  
    s->capabilities &= (~CAP_JUMBO);

/* Assign the routed properly now */
          s->rt_route = other_route;
          s->rt_route_def = other_route;
    }

      break;
  }
}

void gateway_double_check_parameters (tp_Socket *s)
{
  int route_sock_id;
  int s_id;
  route *rt;
  int value;
  int value_size;
  int rc;

  rt = s->rt_route;
  route_sock_id = rt->route_sock_id;
  s_id = s->sockid;

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_RATE) {
    rc = scps_getsockopt (route_sock_id, SCPS_ROUTE, SCPS_RATE, &value, &value_size);
    LOG ("IN RATE getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPS_RATE, &value, value_size);
    LOG ("IN RATE setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MTU) {
    rc = scps_getsockopt (route_sock_id, SCPS_ROUTE, SCPS_MTU, &value, &value_size);
    LOG ("IN MTU getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPS_MTU, &value, value_size);
    LOG ("IN MTU setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_SMTU) {
    rc = scps_getsockopt (route_sock_id, SCPS_ROUTE, SCPS_SMTU, &value, &value_size);
    LOG ("IN SMTU getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPS_SMTU, &value, value_size);
    LOG ("IN SMTU setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MIN_RATE) {
    rc = scps_getsockopt (route_sock_id, SCPS_ROUTE, SCPS_MIN_RATE, &value, &value_size);
    LOG ("IN MIN_RATE getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPS_MIN_RATE, &value, value_size);
    LOG ("IN MIN_RATE setsockopt RC = %d\n", rc);
  }


  if (rt->new_params_flag & GW_ROUTE_ATTRIB_FLOW_CONTROL) {
    rc = scps_getsockopt (route_sock_id, SCPS_ROUTE, SCPS_FLOW_CONTROL, &value, &value_size);
    LOG ("IN FLOW_CONTROL getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPS_FLOW_CONTROL, &value, value_size);
    LOG ("IN FLOW_CONTROL setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_SEND_BUFFER) {
    rc = scps_getsockopt (route_sock_id, SCPS_SOCKET, SCPS_SO_SNDBUF, &value, &value_size);
    LOG ("IN SO_SNDBUF getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_SOCKET, SCPS_SO_SNDBUF, &value, value_size);
    LOG ("IN SO_SNDBUF setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_RECEIVE_BUFFER) {
    rc = scps_getsockopt (route_sock_id, SCPS_SOCKET, SCPS_SO_RCVBUF, &value, &value_size);
    LOG ("IN SO_RCVBUF getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_SOCKET, SCPS_SO_SNDBUF, &value, value_size);
    LOG ("IN SO_RCVBUF setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MIN_RTO_VALUE) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_RTOMIN, &value, &value_size);
    LOG ("IN SCPSTP_RTOMIN getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_RTOMIN, &value, value_size);
    LOG ("IN SCPSTP_RTOMIN setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MAX_RTO_VALUE) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_RTOMAX, &value, &value_size);
    LOG ("IN SCPSTP_RTOMAX getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_RTOMAX, &value, value_size);
    LOG ("IN SCPSTP_RTOMAX setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MAX_RTO_CTR) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_TIMEOUT, &value, &value_size);
    LOG ("IN SCPSTP_TIMEOUT getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_TIMEOUT, &value, value_size);
    LOG ("IN SCPSTP_TIMEOUT setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_MAX_PERSIST_CTR) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_MAXPERSIST_CTR, &value, &value_size);
    LOG ("IN MAXPERSIST_CTR getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_MAXPERSIST_CTR, &value, value_size);
    LOG ("IN MAXPERSIST_CTR setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_RTO_PERSIST_MAX) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_RTOPERSIST_MAX, &value, &value_size);
    LOG ("IN RTOPERSIST_MAX getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_RTOPERSIST_MAX, &value, value_size);
    LOG ("IN RTOPERSIST_MAX setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_RTO_PERSIST_CTR) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_RTOPERSIST_MAX, &value, &value_size);
    LOG ("IN RTOPERSIST_CTR getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_RTOPERSIST_MAX, &value, value_size);
    LOG ("IN RTOPERSIST_CTR setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_EMBARGO_FAST_RXMIT_CTR) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_EMBARGO_FAST_RXMIT_CTR, &value, &value_size);
    LOG ("IN EMBARGO_FAST_RXMIT_CTR getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_EMBARGO_FAST_RXMIT_CTR, &value, value_size);
    LOG ("IN EMBARGO_FAST_RXMIT_CTR setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_TWO_MSL_TIMEOUT) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT, &value, &value_size);
    LOG ("IN TWO_MSL_TIMEOUT getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_2MSLTIMEOUT, &value, value_size);
    LOG ("IN TWO_MSL_TIMEOUT setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_ACK_BEHAVE) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_ACKBEHAVE, &value, &value_size);
    LOG ("IN ACKBEHAVE getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_ACKBEHAVE, &value, value_size);
    LOG ("IN ACKBEHAVE setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_ACK_DELAY) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_ACKDELAY, &value, &value_size);
    LOG ("IN ACKDELAY getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_ACKDELAY, &value, value_size);
    LOG ("IN ACKDELAY setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_ACK_FLOOR) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_ACKFLOOR, &value, &value_size);
    LOG ("IN ACKFLOOR getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_ACKFLOOR, &value, value_size);
    LOG ("IN ACKFLOOR setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_TIME_STAMPS) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_TIMESTAMP, &value, &value_size);
    LOG ("IN TIMESTAMP getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_TIMESTAMP, &value, value_size);
    LOG ("IN TIMESTAMP setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_SNACK) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_SNACK, &value, &value_size);
    LOG ("IN SNACK getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_SNACK, &value, value_size);
    LOG ("IN SNACK setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_SNACK_DELAY) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_SNACK_DELAY, &value, &value_size);
    LOG ("IN SNACK_DELAY getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_SNACK_DELAY, &value, value_size);
    LOG ("IN SNACK_DELAY setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_COMPRESS) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_COMPRESS, &value, &value_size);
    LOG ("IN COMPRESS getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_COMPRESS, &value, value_size);
    LOG ("IN COMPRESS setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_VEGAS_ALPHA) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA, &value, &value_size);
    LOG ("IN VEGAS_ALPHA getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_VEGAS_ALPHA, &value, value_size);
    LOG ("IN VEGAS_ALPHA setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_VEGAS_BETA) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_VEGAS_BETA, &value, &value_size);
    LOG ("IN VEGAS_BETA getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_VEGAS_BETA, &value, value_size);
    LOG ("IN VEGAS_BETA setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_VEGAS_GAMMA) {
    rc = scps_getsockopt (route_sock_id, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA, &value, &value_size);
    LOG ("IN VEGAS_GAMMA getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, PROTO_SCPSTP, SCPSTP_VEGAS_GAMMA, &value, value_size);
    LOG ("IN VEGAS_GAMMA setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_NO_DELAY) {
    rc = scps_getsockopt (route_sock_id, SCPS_SOCKET, SCPS_SO_NDELAY, &value, &value_size);
    LOG ("IN NO_DELAY getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_SOCKET, SCPS_SO_NDELAY, &value, value_size);
    LOG ("IN NO_DELAY setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_TCP_ONLY) {
    rc = scps_getsockopt (route_sock_id, SCPS_SOCKET, SCPS_TCPONLY, &value, &value_size);
    LOG ("IN TCP_ONLY getsockopt RC = %d\n", rc);
    rc = scps_setsockopt (s_id, SCPS_SOCKET, SCPS_TCPONLY, &value, value_size);
    LOG ("IN TCP_ONLY setsockopt RC = %d\n", rc);
  }

  if (rt->new_params_flag & GW_ROUTE_ATTRIB_CONG_CONTROL) { 
    switch (rt->cong_control)  {
      case SCPSTP_CONGEST:
        value = 0;
        rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPSTP_CONGEST, &value, value_size);
        LOG ("IN PURE_RATE RC = %d\n", rc);
      break;

      case SCPSTP_VJ_CONGEST:
        value = 1;
        rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPSTP_VJ_CONGEST, &value, value_size);
        LOG ("IN VJ RC = %d\n", rc);
      break;

      case SCPSTP_VEGAS_CONGEST:
        value = 1;
        rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPSTP_VEGAS_CONGEST, &value, value_size);
        LOG ("IN VEGAS  RC = %d\n", rc);
      break;

      case SCPSTP_FLOW_CONTROL_CONGEST:
        value = 1;
        rc = scps_setsockopt (s_id, SCPS_ROUTE, SCPSTP_FLOW_CONTROL_CONGEST, &value, value_size);
        LOG ("IN FLOW_CONTROL RC = %d\n", rc);
      break;
    }
  }
}


